using System;

namespace PDUConverter
{
    /// <summary>
    /// This class and its contained classes contain all possible values for the
    /// Protocol Identifier.
    /// </summary>
    /// <remarks>The members represent the TP-PID octet in the PDU.</remarks>
    public class ProtocolID
    {
        private const byte iwOffset = 0x20;
        private const byte niwOffset = 0;
        private const byte nuOffset = 0x40;
        private const byte resOffset = 0x80;
        private const byte scOffset = 0xc0;

        private ProtocolID()
        {
        }

        /// <summary>
        /// Extracts the "Reserved" part of the PID.
        /// </summary>
        /// <param name="pid">The PID containing the value.</param>
        /// <returns>The value of the "Reserved" part.</returns>
        /// <exception cref="T:System.ArgumentException">Value is not from the "Reserved" range.</exception>
        public static byte GetReservedValue(byte pid)
        {
            if (!IsReserved(pid))
            {
                throw new ArgumentException("Value is not from the \"Reserved\" range.", "pid");
            }
            return (byte) (pid - 0x80);
        }

        /// <summary>
        /// Gets the "SC Specific Use" part of the ProtocolID.
        /// </summary>
        /// <param name="pid">The PID byte to decode.</param>
        /// <returns>The "SC Specific Use" value.</returns>
        /// <exception cref="T:System.ArgumentException">Value in pid is not from the "SC specific" range.</exception>
        public static byte GetSCSpecificUseValue(byte pid)
        {
            if (!IsSCSpecificUse(pid))
            {
                throw new ArgumentException("Value is not from the \"SC specific\" range.", "pid");
            }
            return (byte) (pid - 0xc0);
        }

        /// <summary>
        /// Determines if the specified value is from the "Reserved" part.
        /// </summary>
        /// <param name="pid">The value to check.</param>
        /// <returns>true if the value is from the reserved part, false otherwise.</returns>
        public static bool IsReserved(byte pid)
        {
            return ((pid >= 0x80) && ((pid - 0x80) <= 0x3f));
        }

        /// <summary>
        /// Determines if the specified PID is from the "SC Specific Use" part.
        /// </summary>
        /// <param name="pid">The value to check.</param>
        /// <returns>true if the value is for SC specific use, false otherwise.</returns>
        public static bool IsSCSpecificUse(byte pid)
        {
            return ((pid >= 0xc0) && ((pid - 0xc0) <= 0x3f));
        }

        /// <summary>
        /// Allows the "Reserved" part of the ProtocolID to be used.
        /// </summary>
        /// <param name="value">The value for this part.</param>
        /// <exception cref="T:System.ArgumentException">Value is greater than 0x3F (63).</exception>
        /// <returns>The encoded protocol ID.</returns>
        public static byte Reserved(byte value)
        {
            if (value > 0x3f)
            {
                throw new ArgumentException("Value must not be greater than 0x3F (63).");
            }
            return (byte) (0x80 + value);
        }

        /// <summary>
        /// Allows the "SC Specific Use" part of the ProtocolID to be used.
        /// </summary>
        /// <param name="value">The value for this part.</param>
        /// <exception cref="T:System.ArgumentException">Value is greater than 0x3F (63).</exception>
        /// <returns>The encoded Protocol ID.</returns>
        public static byte SCSpecificUse(byte value)
        {
            if (value > 0x3f)
            {
                throw new ArgumentException("Value must not be greater than 0x3F (63).");
            }
            return (byte) (0xc0 + value);
        }

        /// <summary>
        /// Telematic interworking.
        /// </summary>
        /// <remarks>
        /// <para>If an interworking protocol is specified in an SMS-SUBMIT PDU,
        /// it indicates that the SME is a telematic device of the specified type,
        /// and requests the SC to convert the SM into a form suited for that
        /// device type. If the destination network is ISDN, the SC must also
        /// select the proper service indicators for connecting to a device of
        /// that type.</para>
        /// 
        /// <para>If an interworking protocol is specified in an SMS-DELIVER PDU,
        /// it indicates that the SME is a telematic device of the specified type.
        /// </para>
        /// </remarks>
        public enum Interworking : byte
        {
            /// <summary>ERMES (European Radio Messaging System)</summary>
            Ermes = 0x25,
            /// <summary>Group 3 Telefax</summary>
            Group3Telefax = 0x22,
            /// <summary>Group 4 Telefax</summary>
            Group4Telefax = 0x23,
            /// <summary>
            /// A GSM mobile station. The SC converts the SM from the received
            /// TP-DCS to any data coding scheme supported by that MS (e.g. the
            /// default).
            /// </summary>
            GsmMobileStation = 0x3f,
            /// <summary>
            /// Implicit - device type is specific to this SC, or can be
            /// concluded on the basis of the address
            /// </summary>
            Implicit = 0x20,
            /// <summary>Internet Electronic Mail</summary>
            InternetEMail = 50,
            /// <summary>A message handling facility (known to the SC)</summary>
            MessageHandler = 0x30,
            /// <summary>National Paging System (known to the SC)</summary>
            PagingSystem = 0x26,
            /// <summary>Reserved (0x0E)</summary>
            Reserved0E = 0x2e,
            /// <summary>Reserved (0x0F)</summary>
            Reserved0F = 0x2f,
            /// <summary>Reserved (0x13)</summary>
            Reserved13 = 0x33,
            /// <summary>Reserved (0x14)</summary>
            Reserved14 = 0x34,
            /// <summary>Reserved (0x15)</summary>
            Reserved15 = 0x35,
            /// <summary>Reserved (0x16)</summary>
            Reserved16 = 0x36,
            /// <summary>Reserved (0x17)</summary>
            Reserved17 = 0x37,
            /// <summary>
            /// Value specific to each SC, usage based on mutual agreement
            /// between the SME and the SC
            /// </summary>
            SCSpecific1 = 0x38,
            /// <summary>
            /// Value specific to each SC, usage based on mutual agreement
            /// between the SME and the SC
            /// </summary>
            SCSpecific2 = 0x39,
            /// <summary>
            /// Value specific to each SC, usage based on mutual agreement
            /// between the SME and the SC
            /// </summary>
            SCSpecific3 = 0x3a,
            /// <summary>
            /// Value specific to each SC, usage based on mutual agreement
            /// between the SME and the SC
            /// </summary>
            SCSpecific4 = 0x3b,
            /// <summary>
            /// Value specific to each SC, usage based on mutual agreement
            /// between the SME and the SC
            /// </summary>
            SCSpecific5 = 60,
            /// <summary>
            /// Value specific to each SC, usage based on mutual agreement
            /// between the SME and the SC
            /// </summary>
            SCSpecific6 = 0x3d,
            /// <summary>
            /// Value specific to each SC, usage based on mutual agreement
            /// between the SME and the SC
            /// </summary>
            SCSpecific7 = 0x3e,
            /// <summary>Teletex, carrier unspecified</summary>
            Teletex = 40,
            /// <summary>Teletex, in CSPDN</summary>
            TeletexCSPDN = 0x2a,
            /// <summary>Teletex, in digital ISDN</summary>
            TeletexISDN = 0x2c,
            /// <summary>Teletex, in PSPDN</summary>
            TeletexPSPDN = 0x29,
            /// <summary>Teletex, in analog PSTN</summary>
            TeletexPSTN = 0x2b,
            /// <summary>Telex (or teletex reduced to telex format)</summary>
            Telex = 0x21,
            /// <summary>UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)</summary>
            Uci = 0x2d,
            /// <summary>Videotex (T.100/T.101)</summary>
            VideoTex = 0x27,
            /// <summary>Voice Telephone (i.e. conversion to speech)</summary>
            VoiceTelephone = 0x24,
            /// <summary>Any public X.400-based message handling system</summary>
            X400BasedHandler = 0x31
        }

        /// <summary>
        /// For network use
        /// </summary>
        /// <remarks>
        /// Details are written in the remarks section of the types.
        /// </remarks>
        public enum NetworkUse : byte
        {
            /// <summary>
            /// ME Data Download
            /// </summary>
            /// <remarks>
            /// <b>ME Data Download</b> is facility whereby the ME shall process the
            /// short message in its entirety including all SMS elements
            /// contained in the SMS deliver to the ME. The DCS shall be set to
            /// message class 1. The entire user data field is available for ME
            /// Data Download.
            /// </remarks>
            MEDataDownload = 0x7d,
            /// <summary>
            /// ME De-personalization Short Message
            /// </summary>
            /// <remarks>
            /// <b>The ME De-personalization Short Message</b> is an ME-specific
            /// message which instructs the ME to de-personalize the ME (see
            /// GSM 2.22). The TP-DCS shall be set to Uncompressed, Default
            /// Alphabet, and Message Class 1 (Me-specific), which corresponds
            /// to a bit coding og 00010001. The TP-UD field contains
            /// de-personalization information coded according to GSM 02.22.
            /// This information shall not be displayed by an ME which supports
            /// the scheme. The acknowledgement to this message is a
            /// SMS-DELIVER-REPORT for RP-ACK in ehich the TP-User-Data shall be
            /// coded according to GSM 02.22.
            /// </remarks>
            MEDepersonalization = 0x7e,
            /// <summary>Replace Short Message Type 1</summary>
            /// <remarks>
            /// <para>The <b>Replace Short Message</b> feature is optional for the ME and
            /// the SIM but if implemented it shall be performed as described here.</para>
            /// 
            /// <para>For MT short messages, on receipt of a short message from from
            /// the SC, the MS shall check to see if the associated Protocol
            /// Identifier contains a Replace Short Message Type code.</para>
            /// 
            /// <para>If such a code is present, the the MS will check the originating
            /// address and replace any existing stored message having the same
            /// Protocol Identifier code and originating address with the new
            /// short message and other parameter values. If there is no message
            /// to be replaced, the MS shall store the message in the normal way.
            /// The MS may also check the SC address as well as the Originating
            /// Address. However, in a network which has multiple SCs, it is
            /// possible for a Replace Message type for a SM to be sent via
            /// different SCs and so it is recommended that the SC address
            /// should not be checked by the MS unless the application
            /// specifically requires such a check.</para>
            /// 
            /// <para>If a Replace Short Message Type code is not present then the MS
            /// will will store the message in the normal way.</para>
            /// 
            /// <para>In MO short messages the SC reacts similarly but only the address
            /// of the originating MS or any other source is checked.</para>
            /// </remarks>
            ReplaceShortMessageType1 = 0x41,
            /// <summary>Replace Short Message Type 2</summary>
            /// <remarks>
            /// The <b>Replace Short Message</b> feature is optional for the ME and
            /// the SIM but if implemented it shall be performed as described
            /// in the remarks section of <see cref="F:GsmComm.PduConverter.ProtocolID.NetworkUse.ReplaceShortMessageType1" />.
            /// </remarks>
            ReplaceShortMessageType2 = 0x42,
            /// <summary>Replace Short Message Type 3</summary>
            /// <remarks>
            /// The <b>Replace Short Message</b> feature is optional for the ME and
            /// the SIM but if implemented it shall be performed as described
            /// in the remarks section of <see cref="F:GsmComm.PduConverter.ProtocolID.NetworkUse.ReplaceShortMessageType1" />.
            /// </remarks>
            ReplaceShortMessageType3 = 0x43,
            /// <summary>Replace Short Message Type 4</summary>
            /// <remarks>
            /// The <b>Replace Short Message</b> feature is optional for the ME and
            /// the SIM but if implemented it shall be performed as described
            /// in the remarks section of <see cref="F:GsmComm.PduConverter.ProtocolID.NetworkUse.ReplaceShortMessageType1" />.
            /// </remarks>
            ReplaceShortMessageType4 = 0x44,
            /// <summary>Replace Short Message Type 5</summary>
            /// <remarks>
            /// The <b>Replace Short Message</b> feature is optional for the ME and
            /// the SIM but if implemented it shall be performed as described
            /// in the remarks section of <see cref="F:GsmComm.PduConverter.ProtocolID.NetworkUse.ReplaceShortMessageType1" />.
            /// </remarks>
            ReplaceShortMessageType5 = 0x45,
            /// <summary>Replace Short Message Type 6</summary>
            /// <remarks>
            /// The <b>Replace Short Message</b> feature is optional for the ME and
            /// the SIM but if implemented it shall be performed as described
            /// in the remarks section of <see cref="F:GsmComm.PduConverter.ProtocolID.NetworkUse.ReplaceShortMessageType1" />.
            /// </remarks>
            ReplaceShortMessageType6 = 70,
            /// <summary>Replace Short Message Type 7</summary>
            /// <remarks>
            /// The <b>Replace Short Message</b> feature is optional for the ME and
            /// the SIM but if implemented it shall be performed as described
            /// in the remarks section of <see cref="F:GsmComm.PduConverter.ProtocolID.NetworkUse.ReplaceShortMessageType1" />.
            /// </remarks>
            ReplaceShortMessageType7 = 0x47,
            /// <summary>
            /// Return Call Message
            /// </summary>
            /// <remarks>
            /// A <b>Return Call Message</b> indicates to the MS to inform the user
            /// that a call (e.g. a telephone call) can be established to the
            /// address specified within the TP-OA. The RP-OA contains the address
            /// of the SC as usual. The message content (if present) gives
            /// displayable information (e.g. the number of waiting voice messages).
            /// The message is handled in the same way as all other messages of
            /// the Replace Short Message Types.
            /// </remarks>
            ReturnCallMessage = 0x5f,
            /// <summary>Short Message Type 0</summary>
            /// <remarks>A <b>Short Message Type 0</b> indicates that the ME must
            /// acknowledge receipt of the short message but may discard its contents.
            /// </remarks>
            ShortMessageType0 = 0x40,
            /// <summary>
            /// SIM Data Download
            /// </summary>
            /// <remarks>
            /// <b>SIM Data Download</b> is a facility whereby the ME must pass the
            /// short message in its entirety including all SMS elements
            /// contained in the SMS deliver to the SIM using the mechanism
            /// descriped in GSM 11.11. The DCS shall be set to 8 bit message
            /// class 2 (either bit coding 11110110 or 00010110). The entire
            /// user data field is available for SIM Data Download.
            /// </remarks>
            SIMDataDownload = 0x7f
        }

        /// <summary>
        /// For the straightforward case of simple MS-to-SC short message
        /// transfer. No interworking is performed.
        /// </summary>
        public enum NoInterworking : byte
        {
            /// <summary>
            /// SME-to-SME protocol. For the straightforward case of simple MS-to-SC short message
            /// transfer. No interworking is performed.
            /// </summary>
            /// <remarks>
            /// If this value is specified in an SMS-DELIVER PDU, the value
            /// indicates the SM-AL protocol being used between the SME and the MS.
            /// </remarks>
            SmeToSmeProtocol = 0
        }
    }
}